// GrayscaleReconstructor.cpp : implementation file
//

#include "stdafx.h"
#include "GrayscaleReconstructor.h"
#include "GrayscaleOpening.h"
#include "GrayscaleClosing.h"
#include "GrayscaleDilation.h"
#include "BinaryDilation.h"
#include "../Color Filters/GrayscaleRMY.h"
#include "../Operators/Copy.h"
#include "../Operators/Mask.h"

// CGrayscaleReconstructor

CGrayscaleReconstructor::CGrayscaleReconstructor() : m_type(OBR), m_seSize(3)
{
}

CGrayscaleReconstructor::~CGrayscaleReconstructor()
{
}


// CGrayscaleReconstructor member functions

BOOL CGrayscaleReconstructor::Apply(CxImage& srcImage, CxImage& destImage)
{
	CxImage* grayImage = &srcImage;
	if (!srcImage.IsGrayScaled())
	{
		grayImage = new CImageEx();
		grayImage->Create(srcImage.GetSize(), srcImage.GetBPP());
		// apply grayscale to the image
		CGrayscaleRMY grayscale;
		grayscale.Apply(srcImage, destImage);
	}

	if (m_type == OBR)
	{
		// apply opening to the image
		CGrayscaleOpening opening(m_seSize);
		opening.Apply(*grayImage, destImage);
	}
	else if (m_type == CBR)
	{
		// apply closing to the image
		CGrayscaleClosing closing(m_seSize);
		closing.Apply(*grayImage, destImage);
	}
	else
		return FALSE;
	
	BOOL bSuccess = Reconstruct(destImage, *grayImage);
	
	if (!srcImage.IsGrayScaled())
		delete grayImage;
	return bSuccess;
}

BOOL CGrayscaleReconstructor::Apply(CxImage& srcImage, CxImage& midImage, CxImage& destImage)
{
	CxImage* grayImage = &srcImage;

	if (!srcImage.IsGrayScaled())
	{
		grayImage = new CImageEx();
		grayImage->Create(srcImage.GetSize(), srcImage.GetBPP());
		// apply grayscale to the image
		CGrayscaleRMY grayscale;
		grayscale.Apply(srcImage, *grayImage);
	}

	if (m_type == OBR)
	{
		// apply opening to the image
		CGrayscaleOpening opening(m_seSize);
		opening.Apply(*grayImage, midImage);
	}
	else if (m_type == CBR)
	{
		// apply closing to the image
		CGrayscaleClosing closing(m_seSize);
		closing.Apply(*grayImage, midImage);
	}
	else
		return FALSE;
	
	// copy the mid image to dest image
	CCopy copier;

	//BOOL bSuccess = copier.Apply(midImage, destImage);
	BOOL bSuccess = copier.Apply(midImage, destImage) 
		&& Reconstruct(destImage, *grayImage);
	
	if (!srcImage.IsGrayScaled())
		delete grayImage;
	return bSuccess;
}

BOOL CGrayscaleReconstructor::Reconstruct(CxImage& srcImage, CxImage& maskImage)
{
	// initialize the dilator according to the srcImage
	IImageFilter *dilator = NULL;
	if (srcImage.IsBinarized())
		dilator = new CBinaryDilation();
	else
		dilator = new CGrayscaleDilation();

	// initialize the mask
	CMask mask(INTERSECTION);
	int i = 19;
	do
	{
		// Step1:perform grayscale dilation
		dilator->Apply(srcImage);
		// Step2:check every value in dilated result is not
		// exceed the restriction of mask 
		mask.Apply(srcImage, maskImage);
		i--;
	} while (i > 0);

	delete dilator;
	return TRUE;
}